/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.configuration.tree; import java.util.Iterator; import java.util.List; import java.util.StringTokenizer; import junit.framework.TestCase; /** * Test class for DefaultConfigurationNode. * * @author Oliver Heger */ public class TestDefaultConfigurationNode extends TestCase { /** Constant array for the field names. */ private static final String[] FIELD_NAMES = { "UID", "NAME", "FIRSTNAME", "LASTLOGIN"}; /** Constant array for the field data types. */ private static final String[] FIELD_TYPES = { "long", "string", "string", "date"}; /** Constant array for additional field attributes. */ private static final String[] FIELD_ATTRS = { "primarykey,unique", "notnull", "notnull", null}; /** The node to be tested. */ DefaultConfigurationNode node; protected void setUp() throws Exception { super.setUp(); node = new DefaultConfigurationNode(); node.setName("table"); node.setReference("TestReference"); node.addAttribute(new DefaultConfigurationNode("type", "system")); node.addChild(new DefaultConfigurationNode("name", "users")); // Add nodes for the table's fields for (int i = 0; i < FIELD_NAMES.length; i++) { DefaultConfigurationNode field = new DefaultConfigurationNode( "field"); field .addChild(new DefaultConfigurationNode("name", FIELD_NAMES[i])); field.addAttribute(new DefaultConfigurationNode("type", FIELD_TYPES[i])); if (FIELD_ATTRS[i] != null) { StringTokenizer tok = new StringTokenizer(FIELD_ATTRS[i], ", "); while (tok.hasMoreTokens()) { field.addAttribute(new DefaultConfigurationNode( "attribute", tok.nextToken())); } } node.addChild(field); } } /** * Tests a newly created, uninitialized node. */ public void testNewNode() { node = new DefaultConfigurationNode(); assertNull("name is not null", node.getName()); assertNull("value is not null", node.getValue()); assertNull("reference is not null", node.getReference()); assertTrue("Children are not empty", node.getChildren().isEmpty()); assertTrue("Named children are not empty", node.getChildren("test") .isEmpty()); assertEquals("Children cound is not 0", 0, node.getChildrenCount()); assertEquals("Named children count is not 0", 0, node .getChildrenCount("test")); assertTrue("Attributes are not empty", node.getAttributes().isEmpty()); assertTrue("Named attributes are not empty", node.getAttributes("test") .isEmpty()); assertNull("Node has a parent", node.getParentNode()); assertFalse("Node is defined", node.isDefined()); try { node.getAttribute(0); fail("Could access non existing attribute!"); } catch (IndexOutOfBoundsException iex) { // ok } } /** * Tests accessing a node's reference. */ public void testGetReference() { assertEquals("Reference was not stored", "TestReference", node .getReference()); } /** * Tests accessing the node's children. */ public void testGetChildren() { assertEquals("Number of children incorrect", FIELD_NAMES.length + 1, node.getChildrenCount()); List children = node.getChildren(); Iterator it = children.iterator(); DefaultConfigurationNode child = (DefaultConfigurationNode) it.next(); assertEquals("Wrong node", "name", child.getName()); checkFieldNodes(it); } /** * Tests accessing the node's children by name. */ public void testGetChildrenByName() { List children = node.getChildren("field"); assertEquals("Incorrect number of child nodes", FIELD_NAMES.length, children.size()); assertEquals("Incorrect result of getChildrenCount()", FIELD_NAMES.length, node.getChildrenCount("field")); checkFieldNodes(children.iterator()); assertTrue("Found non existing nodes", node.getChildren("test") .isEmpty()); assertEquals("Wrong children list for null", node.getChildren(), node .getChildren(null)); } /** * Tests adding a new child node. */ public void testAddChild() { int cnt = node.getChildrenCount(); DefaultConfigurationNode ndNew = new DefaultConfigurationNode("test", "xyz"); node.addChild(ndNew); assertEquals("New node was not added", cnt + 1, node.getChildrenCount()); List children = node.getChildren(); assertEquals("Incorrect number of children", node.getChildrenCount(), children.size()); assertSame("Node was not added to end", ndNew, children.get(cnt)); assertEquals("Incorrect number of named children", 1, node .getChildrenCount(ndNew.getName())); assertFalse("Child is an attribute", ndNew.isAttribute()); assertSame("Parent was not set", node, ndNew.getParentNode()); } /** * Tests adding invalid child nodes. */ public void testAddUndefinedChild() { try { node.addChild(null); fail("null node could be added!"); } catch (IllegalArgumentException iex) { // ok } try { node.addChild(new DefaultConfigurationNode()); fail("Node without name could be added!"); } catch (IllegalArgumentException iex) { // ok } } /** * Tests removing a child node. */ public void testRemoveChild() { DefaultConfigurationNode child = (DefaultConfigurationNode) node .getChildren().get(3); int cnt = node.getChildrenCount(); node.removeChild(child); assertEquals("Child was not removed", cnt - 1, node.getChildrenCount()); for (Iterator it = node.getChildren().iterator(); it.hasNext();) { assertNotSame("Found removed node", child, it.next()); } assertNull("Parent reference was not removed", child.getParentNode()); } /** * Tests removing a child node that does not belong to this node. */ public void testRemoveNonExistingChild() { int cnt = node.getChildrenCount(); node.removeChild(new DefaultConfigurationNode("test")); node.removeChild(new DefaultConfigurationNode()); node.removeChild((ConfigurationNode) null); node.removeChild("non existing child node"); node.removeChild((String) null); assertEquals("Children were changed", cnt, node.getChildrenCount()); } /** * Tests removing children by their name. */ public void testRemoveChildByName() { int cnt = node.getChildrenCount(); node.removeChild("name"); assertEquals("Child was not removed", cnt - 1, node.getChildrenCount()); assertEquals("Still found name child", 0, node.getChildrenCount("name")); node.removeChild("field"); assertEquals("Still remaining nodes", 0, node.getChildrenCount()); } /** * Tests removing all children at once. */ public void testRemoveChildren() { node.removeChildren(); assertEquals("Children count is not 0", 0, node.getChildrenCount()); assertTrue("Children are not empty", node.getChildren().isEmpty()); } /** * Tests accessing a child by its index. */ public void testGetChild() { ConfigurationNode child = node.getChild(2); assertEquals("Wrong child returned", child, node.getChildren().get(2)); } /** * Tests accessing child nodes with invalid indices. */ public void testGetChildInvalidIndex() { try { node.getChild(4724); fail("Could access invalid index!"); } catch (IndexOutOfBoundsException iex) { // ok } } /** * Tests accessing the node's attributes. */ public void testGetAttributes() { assertEquals("Number of attributes incorrect", 1, node .getAttributeCount()); List attributes = node.getAttributes(); Iterator it = attributes.iterator(); DefaultConfigurationNode attr = (DefaultConfigurationNode) it.next(); assertEquals("Wrong node", "type", attr.getName()); assertFalse("More attributes", it.hasNext()); } /** * Tests accessing the node's attributes by name. */ public void testGetAttributesByName() { assertEquals("Incorrect number of attributes", 1, node .getAttributeCount("type")); DefaultConfigurationNode field = (DefaultConfigurationNode) node .getChildren().get(1); assertEquals("Incorrect number of attributes", 2, field .getAttributeCount("attribute")); List attrs = field.getAttributes("attribute"); assertEquals("Wrong value", "primarykey", ((DefaultConfigurationNode) attrs.get(0)).getValue()); assertEquals("Wrong value", "unique", ((DefaultConfigurationNode) attrs .get(1)).getValue()); } /** * Tests adding a new attribute node. */ public void testAddAttribute() { int cnt = node.getAttributeCount(); DefaultConfigurationNode ndNew = new DefaultConfigurationNode("test", "xyz"); node.addAttribute(ndNew); assertEquals("New node was not added", cnt + 1, node .getAttributeCount()); List attrs = node.getAttributes(); assertEquals("Incorrect number of attributes", node.getAttributeCount(), attrs.size()); assertSame("Node was not added to end", ndNew, attrs.get(cnt)); assertEquals("Incorrect number of named attributes", 1, node .getAttributeCount(ndNew.getName())); assertTrue("Child is no attribute", ndNew.isAttribute()); assertSame("Parent was not set", node, ndNew.getParentNode()); } /** * Tests removing an attribute node. */ public void testRemoveAttribute() { DefaultConfigurationNode attr = (DefaultConfigurationNode) node .getAttributes().get(0); int cnt = node.getAttributeCount(); node.removeAttribute(attr); assertEquals("Attribute was not removed", cnt - 1, node .getAttributeCount()); for (Iterator it = node.getAttributes().iterator(); it.hasNext();) { assertNotSame("Found removed node", attr, it.next()); } assertNull("Parent reference was not removed", attr.getParentNode()); } /** * Tests removing attributes by their names. */ public void testRemoveAttributeByName() { ConfigurationNode field = node.getChild(1); assertEquals("Incorrect number of attributes", 3, field .getAttributeCount()); field.removeAttribute("attribute"); assertEquals("Not all nodes removed", 1, field.getAttributeCount()); assertTrue("Remaining attributes", field.getAttributes("attribute") .isEmpty()); field.removeAttribute("type"); assertEquals("Remaining attributes", 0, field.getAttributeCount()); } /** * Tests removing all attributes. */ public void testRemoveAttributes() { node.removeAttributes(); assertEquals("Not all attributes removed", 0, node.getAttributeCount()); assertTrue("Attributes not empty", node.getAttributes().isEmpty()); } /** * Tests changing a node's attribute state. */ public void testChangeAttributeState() { ConfigurationNode attr = node.getAttribute(0); try { attr.setAttribute(false); fail("Could change node's attribute state!"); } catch (IllegalStateException iex) { // ok } } /** * Tests the visit() method using a simple visitor. */ public void testVisit() { CountNodeVisitor visitor = new CountNodeVisitor(); node.visit(visitor); assertEquals("Not all nodes visited", 19, visitor.beforeCalls); assertEquals("Different number of before and after calls", visitor.beforeCalls, visitor.afterCalls); } /** * Tests the visit() method with a visitor that terminates the visit * process. */ public void testVisitWithTerminate() { CountNodeVisitor visitor = new CountNodeVisitor(10); node.visit(visitor); assertEquals("Incorrect number of nodes visited", visitor.maxCalls, visitor.beforeCalls); assertEquals("Different number of before and after calls", visitor.beforeCalls, visitor.afterCalls); } /** * Tests the visit() method when null is passed in. This should throw an * exception. */ public void testVisitWithNullVisitor() { try { node.visit(null); fail("Could pass in null visitor!"); } catch (IllegalArgumentException iex) { // ok } } /** * Tests cloning a node. */ public void testClone() { node.setValue("TestValue"); DefaultConfigurationNode clone = (DefaultConfigurationNode) node.clone(); assertEquals("Value not cloned", "TestValue", clone.getValue()); assertEquals("Name not cloned", "table", clone.getName()); assertEquals("Reference not cloned", "TestReference", clone.getReference()); assertEquals("Children were cloned", 0, clone.getChildrenCount()); assertEquals("Attributes were cloned", 0, clone.getAttributeCount()); } /** * Helper method for checking the child nodes of type "field". * * @param itFields the iterator with the child nodes */ private void checkFieldNodes(Iterator itFields) { for (int i = 0; i < FIELD_NAMES.length; i++) { DefaultConfigurationNode child = (DefaultConfigurationNode) itFields .next(); assertEquals("Wrong node", "field", child.getName()); List nameNodes = child.getChildren("name"); assertEquals("Wrong number of name nodes", 1, nameNodes.size()); DefaultConfigurationNode nameNode = (DefaultConfigurationNode) nameNodes .get(0); assertEquals("Wrong field name", FIELD_NAMES[i], nameNode .getValue()); } } /** * A test visitor implementation that is able to count the number of visits. * It also supports a maximum number of visits to be set; if this number is * reached, the <code>terminate()</code> method returns <b>true</b>. */ static class CountNodeVisitor implements ConfigurationNodeVisitor { public int beforeCalls; public int afterCalls; public int maxCalls; public CountNodeVisitor() { this(Integer.MAX_VALUE); } public CountNodeVisitor(int maxNumberOfVisits) { maxCalls = maxNumberOfVisits; } public void visitBeforeChildren(ConfigurationNode node) { beforeCalls++; } public void visitAfterChildren(ConfigurationNode node) { afterCalls++; } public boolean terminate() { return beforeCalls >= maxCalls; } } }